最近在玩 WRTnode (http://wrtnode.cc),為此也做了幾個小應用程式跟這塊可愛的小板子進行互動,不過之間涉及到網路的聯通動作都還只能在內網下操作,雖說在外網的操作可以藉由像是 MQTT 來達成,不過資料總還是得透過一個中繼伺服器來進行傳輸,總覺得不怎麼可靠呢!
不過在市面上找到一個 P2P 的連線解決方案 Kalay,就讓我們來試試骨子裡賣什麼藥吧!
Requirements
- WRTnode
- Android 手機 (也可以用模擬器)
- 一顆熱誠的心
What will we learn
在本次的主題中,將會建立一個 Android App,用以和 WRTnode 互動,在 App 上按下按鈕,將會開啟或關閉 WRTnode 上的 LED 燈。在這個實作上我們將會分為二個部分進行:
- WRTnode 撰寫 Restful API,讓 Web Client 可以透過 Restful API 控制板子上的 LED。
- 撰寫 Android App,並使用 WRTnode 的 Restful API。
Let’s start with WRTnode
在拿到 WRTnode 之後發現這塊板子沒有網路孔,看來只能先透過無線網路方式連到它再進行設定了,所幸 WRTnode 官網上的設定方式 還算親民,從設定對外網路到可以透過 SSH 連線進 WRTnode 約半小時內可完成。
WRTnode 也原生支援 python,因此可以透過 python web framework 完成我們的 API。這邊我用的 python web framework 是 Bottle,Bottle 的安裝方式相對容易,可以直接透過 wget 下載。
1 | wget --no-check-certificate https://github.com/bottlepy/bottle/raw/master/bottle.py |
在此之前,我們先小試一下 Bottle 的功能,下面是 Bottle 官網上的小程式,我們拿來試一下效果。
1 | from bottle import route, run, template |
執行上面的 python 程式碼後,WRTnode 將會運行一個 Listen 8080 port 的 web server,這時我們可以透過瀏覽器看一下執行結果。
那麼,要怎麼使用 python 控制 LED 燈呢?下面是個簡單的範例,執行這個程式後,WRTnode 上的 LED 燈將會 blink blink 的閃個不停喔!
1 | import os, time |
太好了!如果把上面二個程式結合在一起,不就可以透過 web browser 控制 LED 了嗎?
1 | from bottle import route, run |
執行上面的程式後,便可以透過 web browser 操作 WRTnode 上的 LED 燈了。
- 開啟 LED 燈:
http://%IP%:8080/led/on
- 關閉 LED 燈:
http://%IP%:8080/led/off
讓我先告一段落在 WRTnode 上的實作,接下來我們要撰寫 Android App 控制 WRTnode。
當然,在開發 Android 應用程式之前,要先將開發工具打點好,這邊我選用的是 Android Studio 1.3.2 (http://developer.android.com/sdk),Android Studio 的安裝及設定在此就不介紹了,需要這方面資訊的朋友可以前往 Google 大神詢問。
在安裝好 Android Studio 之後,我們先來建立個應用程式吧,然後我們在 Activity 上加入二個按鈕,分別用作開啟及關閉 LED 燈。
以下是我自己應用程式的 layout。
1 | <RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android" |
接下來為了能讓應用程式可以連上網路,因此必須給予 Internet accessible 的 permission。
1 | <uses-permission android:name="android.permission.INTERNET" /> |
在這個應用程式中,我使用了 Volley 來存取 HTTP,所以必須在 Gradle 中加入。
1 | compile 'com.mcxiaoke.volley:library:1.0.18' |
最後我們在主程式 (MainActivity.java) 中撰寫這二個按鈕的程式。
1 | static final String TAG = "LED_SWITCH"; |
好了,在程式順利編譯執行後,按下「On」、「Off」按鈕,可以在 logcat 中看到 WRTnode 的回覆。
Use Kalay SDK
截至目前為止,我們都可以在內網 (LAN) 中存取 WRTnode 的 HTTP 服務,但如果我們要在外網的環境下存取 WRTnode 的話,勢必得設定 Router 進行 port-mapping 或是 port-forwarding 了。所幸我們今天要介紹的 Kalay 提供了另一種簡決方式,透過簡易的 API 使用,便可以 P2P tunneling 的方法存取遠端的裝置。
在 Kalay Starter Kit 中提供了給 WRTnode 使用的 C library,我們可以使用 WRTnode 的交叉編譯器 (Cross compiler) 產出 Kalay P2PTunnel 執行檔 (Daemon) 放在 WRTnode 上執行。
在 WRTnode 的 wiki 官網上可以下載預先編譯好的 tool-chain,我這邊使用 Ubuntu 14.04LTS 下載後並解壓縮。
在佈置好 WRTnode 的 tool-chain 後,我們先以 Kit 中的 Sample code 試著編譯看看。
1 | $ export CC=%WRTNODE_TOOL_CHAIN_FOLDER%/bin/mipsel-openwrt-linux-uclibc-gcc |
編譯成功後,我們將 P2PTunnelServer 以及 Kalay SDK 的 Library 檔案丟到 WRTnode 上執行。
1 | LD_LIBRARY_PATH=%KALAY_KIT_LIB_FOLDER% ./P2PTunnelServer %UID% |
這時已經完成 WRTnode 的整合,接下來進行的是 Android App 上的整合。
從 Kalay Starter Kit 中發現提供給 Android 使用的是 Native Library,在 Android Studio 中使用 Native Library 則必須將這些檔案丟到特定的目錄中。
app/src/main/jniLibs/armeabi/xxx.so
app/src/main/jniLibs/x86/xxx.so
在完成 Library 及 wrapper class 的佈署後,我們在畫面上新增一個文件方塊及按鈕。
1 | <RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android" |
在這個新的應用程式,我們必須先輸入 Kalay UID,然後按下 CONNECT
按鈕,待 App 與 WRTnode 成功後,才得使用 LED ON
及 LED OFF
這二個按鈕進行控制。
1 | public class MainActivity extends ActionBarActivity implements P2PTunnelAPIs.IP2PTunnelCallback { |
讓我們編譯進執行,然後輸入 WRTnode 的 UID,按下 CONNECT
按鈕,成功建立連線後,就可以操作 LED 燈號了!
透過上述的實作,我們明白即便在外網,透過 Kalay 也能夠簡易地連線到遠端的裝置。
上述 Android 程式碼可於 Github 上下載 (https://github.com/cloudhsiao/led_switch)。
本文章以 方式授權。